/**
 * 项目名：化工企业安全生产信息化管理平台
 * 日期：    2020-03-17 14:00:29
 * Copyright (c) 2015- -版权所有
 */

package com.joysuch.wwyt.edu.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.joysuch.wwyt.alert.service.AlertMessageService;
import com.joysuch.wwyt.api.dataaccess.DataAccessService;
import com.joysuch.wwyt.bp.constant.AppNotifyContentPre;
import com.joysuch.wwyt.bp.entity.contractor.BpContractor;
import com.joysuch.wwyt.bp.entity.contractor.BpContractorStaff;
import com.joysuch.wwyt.bp.repository.BpContractorStaffDao;
import com.joysuch.wwyt.bp.repository.BpDepartDao;
import com.joysuch.wwyt.bp.repository.BpJobDao;
import com.joysuch.wwyt.bp.service.BpContractorService;
import com.joysuch.wwyt.bp.service.BpContractorStaffService;
import com.joysuch.wwyt.common.entity.CommonBusinessNotice;
import com.joysuch.wwyt.common.entity.CommonType;
import com.joysuch.wwyt.common.enums.AppBusinessNoticeTypes;
import com.joysuch.wwyt.common.enums.CommonTypes;
import com.joysuch.wwyt.common.repository.CommonTypeDao;
import com.joysuch.wwyt.common.service.CommonBusinessNoticeService;
import com.joysuch.wwyt.common.service.CommonIndexNotifyService;
import com.joysuch.wwyt.common.service.CommonTypeService;
import com.joysuch.wwyt.config.RedisClient;
import com.joysuch.wwyt.core.bean.BaseAttachmentBean;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.common.util.PageDataUtils.PageDataConvert;
import com.joysuch.wwyt.core.common.util.SimpleDateFormatCache;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.enums.BaseConfigCodes;
import com.joysuch.wwyt.core.enums.DeleteFlag;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.ApiBusinessException;
import com.joysuch.wwyt.core.exception.BusinessRestrictionsException;
import com.joysuch.wwyt.core.mapper.BaseUserMapper;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.service.*;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.edu.bean.*;
import com.joysuch.wwyt.edu.bean.EduTrainningRecordListBean.SearchEduTrainningRecord;
import com.joysuch.wwyt.edu.bean.dto.TrainningRelevanceDto;
import com.joysuch.wwyt.edu.bean.vo.*;
import com.joysuch.wwyt.edu.entity.*;
import com.joysuch.wwyt.edu.entity.dsl.QEduTrainningRecord;
import com.joysuch.wwyt.edu.enums.*;
import com.joysuch.wwyt.edu.mapper.*;
import com.joysuch.wwyt.edu.repository.*;
import com.joysuch.wwyt.edu.service.EduAsyncService;
import com.joysuch.wwyt.edu.service.EduCoursewareService;
import com.joysuch.wwyt.edu.service.EduTrainningPlanService;
import com.joysuch.wwyt.edu.service.EduTrainningRecordService;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.redisson.api.RKeys;
import org.redisson.api.RedissonClient;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import java.io.IOException;
import java.text.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class EduTrainningRecordServiceImpl implements EduTrainningRecordService {

    @Autowired
    private EduTrainningRecordDao dao;
    @Autowired
    private BizCodeGeneratorFacade bizCodeGeneratorFacade;
    @Autowired
    private EduTrainningPlanDao eduTrainningPlanDao;
    @Autowired
    private EduTrainningPlanService eduTrainningPlanService;
    @Autowired
    private CommonTypeDao commonTypeDao;
    @Autowired
    private BpDepartDao bpDepartDao;
    @Resource
    private WwytBpDepartMapper wwytBpDepartMapper;
    @Resource
    private EduTrainningRecordUserMapper eduTrainningRecordUserMapper;
    @Resource
    private EduTrainningRecordMapper eduTrainningRecordMapper;
    @Autowired
    private BaseUserDao baseUserDao;
    @Resource
    private BaseUserMapper baseUserMapper;
    @Autowired
    private EduExamDao eduExamDao;
    @Autowired
    private EduCertificateDao eduCertificateDao;
    @Autowired
    private EduCertificateUserDao eduCertificateUserDao;
    @Autowired
    private EduTrainningRecordImageDao eduTrainningRecordImageDao;
    @Autowired
    private EduExamRecordDao eduExamRecordDao;
    @Autowired
    private EduTrainningRecordUserDao eduTrainningRecordUserDao;
    @Autowired
    private BaseImageRepositoryService baseImageRespositoryService;
    @Autowired
    private CommonTypeService commonTypeService;
    @Autowired
    private BpContractorStaffService bpContractorStaffService;
    @Autowired
    private BpContractorService bpContractorService;
    @Autowired
    private DataAccessService dataAccessService;

    @Autowired
    private BpJobDao jobDao;

    @Autowired
    private WwytEduCertificateUserMapper wwytEduCertificateUserMapper;

    @Autowired
    private BpContractorStaffDao bpContractorStaffDao;

    @Autowired
    private EduTrainningRecordCourseMapper eduTrainningRecordCourseMapper;

    @Autowired
    private EduExamMapper eduExamMapper;

    @Autowired
    private EduTrainningRecordCourseDao eduTrainningRecordCourseDao;

    @Autowired
    private EduExamUserScopeDao eduExamUserScopeDao;

    @Autowired
    private EduCourseMapper eduCourseMapper;

    @Autowired
    private BaseUserService baseUserService;

    @Autowired
    private BaseConfigService baseConfigService;

    @Autowired
    private AlertMessageService alertMessageService;

    @Autowired
    private CommonIndexNotifyService commonIndexNotifyService;

    @Autowired
    private CommonBusinessNoticeService commonBusinessNoticeService;
    @Autowired
    private EduCoursewareService eduCoursewareService;
    @Autowired
    private EduAsyncService eduAsyncService;
    @Autowired
    private EduExamTestPaperDao eduExamTestPaperDao;
    @Autowired
    private EduTestPaperQuestionDao eduTestPaperQuestionDao;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private RedisClient redisClient;
    @Override
    public EduTrainningRecord add(EduTrainningRecordEditBean entity) {
        validateExamAndCert(entity);
        if (eduTrainningRecordMapper.selectTrainingByName(entity.getTrainingName())>0){
            throw new IllegalArgumentException("培训活动名称已存在");
        }
        EduTrainningRecord content = new EduTrainningRecord();
        if (StringUtils.isNotBlank(entity.getCode())) {
            Assert.isTrue(dao.countOfCode(entity.getCode()) == 0, String.format("编号%s已经存在", entity.getCode()));
            content.setCode(entity.getCode());
        } else {
            content.setCode(bizCodeGeneratorFacade.peiXunJiLu());
        }
        BeanUtils.copyProperties(entity, content, "id", "code");
        if (entity.getExamId() != null) {
             content.setExamPassScore(eduExamDao.sumPassScore(entity.getExamId()));
        }
        if (CollectionUtils.isNotEmpty(entity.getAttachments())) {
            content.setAttachments(JSON.toJSONString(entity.getAttachments()));
        }
        content.setTrainingPublishStatus(TrainingPublishStatus.UN_PUBLISH.getId());
        // 保存现场图片
        EduTrainningRecord save = dao.save(content);
        saveImages(content, entity.getImages(), true);

        // 保存参与人员
        saveJoinInUsers(content, entity.getUsers(), null);
        if (entity.getTrainningTypeId() != null) {
            commonTypeService.updateTypeCount(CommonTypes.TRAINNING_RECORD, entity.getTrainningTypeId());
        }
        if (entity.getTrainningPlanId() != null && entity.getTrainningPlanId() > 0) {
            eduTrainningPlanService.updateTrainStatus(entity.getTrainningPlanId());
        }
        //将关联的考试，人员和时间修改为已培训为准
        updateExam(entity);
        //保存线上培训关联的课程
        saveCourse(entity,save.getId());
        //调数据接入接口
        dataAccess(save);
        return content;

    }
    private List<Long> findUserIds(String orgType, List<Long> joinInTargetIds) {
        if ("J".equals(orgType) || "D".equals(orgType)) {
            joinInTargetIds = baseUserService.findUserIdsByTargetIds(orgType, joinInTargetIds);
        }
        return joinInTargetIds;

    }
    private void updateExam(EduTrainningRecordEditBean entity) {
        if (entity.getExamId()!=null){
            //选择考试模式为先学后考 检查否关联课程
            if (entity.getExamMode()==ExamMode.STUDY_EXAM.getId()&&CollectionUtil.isEmpty(entity.getCourseBeans())){
               throw new IllegalArgumentException("考试模式为先学后考，必须绑定一个课程！");
            }

            eduExamDao.updateExamMode(entity.getExamId(),entity.getExamMode());
            //培训活动关联了考试，并且考试已设置了考试人员和考试时间，
            // 则考试人员已培训人员为准，考试时间已培训时间为准
            eduExamUserScopeDao.deleteByExamId(entity.getExamId());
//            eduTrainningRecordMapper.deleteExamUser(entity.getExamId());
            List<EduTrainningRecordUserEditBean> users = entity.getUsers();
            //考试id  参与对象  ids
            List<EduExamUserScope> collect = users.stream().map(u ->
                    new EduExamUserScope(entity.getExamId(), ExamJoinInTargetTypes.USER.getCode(), u.getUserId())
            ).collect(Collectors.toList());
            //更新考试时间
            eduTrainningRecordMapper.updateExamTime(entity.getTrainningDate(),entity.getTrainningEndDate(),entity.getExamId());
            eduExamUserScopeDao.saveAll(collect);

//            eduTestPaperQuestionDao.deleteByExamId(entity.getExamId());
            List<Long> testPapers=eduExamMapper.selectTestPaperByExam(entity.getExamId());
            List<Long> userIds = entity.getUsers().stream().map(EduTrainningRecordUserEditBean::getUserId).collect(Collectors.toList());
            eduAsyncService.saveRelatedTestPapers(entity.getExamId(),testPapers,userIds,new CommonBean());
        }
    }

    private void saveCourse(EduTrainningRecordEditBean entity,Long id) {
        eduTrainningRecordCourseMapper.deleteCourseById(id);
        List<Long> courseBeans = entity.getCourseBeans();
        if (courseBeans!=null&&courseBeans.size()>0){
            List<EduTrainningRecordCourse> collect = courseBeans.stream().map(l -> {
                EduTrainningRecordCourse eduTrainningRecordCourse = new EduTrainningRecordCourse();
                eduTrainningRecordCourse.setTrainningRecordId(id);
                eduTrainningRecordCourse.setCourseId(l);
                eduTrainningRecordCourse.setTenentId(Context.getCurrentTenantId());
                eduTrainningRecordCourse.setCreateBy(Context.getCurrentUserId());
                eduTrainningRecordCourse.setCreateTime(new Date());
                return eduTrainningRecordCourse;
            }).collect(Collectors.toList());
            eduTrainningRecordCourseDao.saveAll(collect);
        }
    }

    /**
     * @param entity
     */
    protected void validateExamAndCert(EduTrainningRecordEditBean entity) {
        if ("Y".equals(entity.getHasCert())) {
            Assert.notNull(entity.getCertId(), "有证书的情况下，证书不能为空，请选择证书");
        }
        if ("Y".equals(entity.getHasExam())) {
            Assert.notNull(entity.getExamId(), "有考试的情况下，考试不能为空，请选择考试");
        }
        if (entity.getTrainingForm()==0){
            Assert.notNull(entity.getTrainningPlace(), "线下培训，培训地点不能为空");
            Assert.notNull(entity.getTrainningTeacherId(), "线下培训，培训讲师不能为空");
            if (!entity.getHasExam().equals("Y") && entity.getHasSignIn() != 1) {
               throw new IllegalArgumentException("是否需要签到、是否有考试必须有一项选择是");
            }
        }
        if (entity.getTrainingForm()==1&&CollectionUtil.isEmpty(entity.getCourseBeans())){
            throw new IllegalArgumentException("线上培训，关联课程不能为空");
        }
    }

    private void saveJoinInUsers(EduTrainningRecord content, List<EduTrainningRecordUserEditBean> users, List<Long> deleteIds) {
        String orgCode = Context.getCurrentOrgCode();
        Long tenantId = Context.getCurrentTenantId();
        Long userId = Context.getCurrentUserId();
        eduTrainningRecordUserMapper.deleteByIds(content.getId());
//        if (CollectionUtil.isNotEmpty(deleteIds)) {
//            eduTrainningRecordUserDao.deleteByIds(deleteIds);
//        }
        if (users == null || users.isEmpty()) {
            return;
        }
        List<EduTrainningRecordUser> list = users.stream().map(image -> {
            EduTrainningRecordUser e = new EduTrainningRecordUser();
            BeanUtils.copyProperties(image, e);
            e.setTrainningRecordId(content.getId());
            e.setHasSignIn(TrainingUserSignStatus.ONLINE.getId());
            e.setOrgCode(orgCode);
            e.setTenentId(tenantId);
            e.setUpdateBy(userId);
            e.setDeleteFlag(DeleteFlag.EFFECTIVE.getCode());
            return e;
        }).collect(Collectors.toList());
        eduTrainningRecordUserDao.saveAll(list);
    }

    private void saveImages(EduTrainningRecord content, List<BaseAttachmentBean> images, boolean add) {
        if (!add) {
            eduTrainningRecordImageDao.deleteByTrainningRecordId(content.getId());
        }
        if (images == null || images.isEmpty()) {
            return;
        }
        List<EduTrainningRecordImage> list = images.stream().map(image -> {
            EduTrainningRecordImage e = new EduTrainningRecordImage();
            e.setImageId(image.getId());
            e.setTrainningRecordId(content.getId());
            return e;
        }).collect(Collectors.toList());
        eduTrainningRecordImageDao.saveAll(list);
    }

    @Override
    public void update(EduTrainningRecordEditBean entity) {
        validateExamAndCert(entity);
        EduTrainningRecord content = dao.findById(entity.getId()).get();
        Long prevPlanId = content.getTrainningPlanId();
        Long newTypeId = entity.getTrainningTypeId();
        Long oldTypeId = content.getTrainningTypeId();
        // Assert.notNull(entity.getCode(), "编号不能为空");
        // Assert.isTrue(dao.countOfCodeExcludeId(entity.getCode(), entity.getId()) == 0,
        // String.format("编号%s已经存在", entity.getCode()));
        // content.setCode(entity.getCode());
        BeanUtils.copyProperties(entity, content, "id", "code");
        if (CollectionUtils.isNotEmpty(entity.getAttachments())) {
            content.setAttachments(JSON.toJSONString(entity.getAttachments()));
        }else {
            content.setAttachments(null);
        }
        if (Objects.equals(content.getExamId(), entity.getExamId())) {
            content.setExamPassScore(eduExamDao.sumPassScore(entity.getExamId()));
        }
        EduTrainningRecord save = dao.save(content);
        // 保存现场图片
        saveImages(content, entity.getImages(), false);
        // 保存参与人员
        saveJoinInUsers(content, entity.getUsers(), entity.getDeleteIds());

        if (Objects.equals(newTypeId, oldTypeId)) {
            commonTypeService.updateTypeCount(CommonTypes.TRAINNING_RECORD, newTypeId);
            commonTypeService.updateTypeCount(CommonTypes.TRAINNING_RECORD, oldTypeId);
        }
        if (prevPlanId != null && prevPlanId > 0) {
            eduTrainningPlanService.updateTrainStatus(prevPlanId);
        }
        if (entity.getTrainningPlanId() != null && entity.getTrainningPlanId() > 0) {
            eduTrainningPlanService.updateTrainStatus(entity.getTrainningPlanId());
        }
        //将关联的考试，人员和时间修改为已培训为准
        updateExam(entity);
        //保存线上培训关联的课程
        saveCourse(entity,save.getId());
        //调数据接入接口
        dataAccess(save);
    }

    public void dataAccess(EduTrainningRecord content) {
        Long typeId = content.getTrainningTypeId();
        String typeName = commonTypeDao.getNameById(typeId);
        if ("现场培训".equals(typeName)) {
            dataAccessService.sceneTrain(content);
        } else if ("风险培训".equals(typeName)) {
            dataAccessService.trainRecord(content);
        }
    }

    @Override
    public Page<EduTrainningRecordListBean> findByPage(Pageable page, SearchEduTrainningRecord condition) {
        Predicate predicate = prepareListSearchCondition(condition);

        Page<EduTrainningRecord> data = predicate == null ? dao.findAll(page) : dao.findAll(predicate, page);

        return PageDataUtils.convertPageData(data,
                new PageDataConvert<EduTrainningRecordListBean, EduTrainningRecord>() {

                    @Override
                    public EduTrainningRecordListBean convert(EduTrainningRecord f) {
                        EduTrainningRecordListBean bean = new EduTrainningRecordListBean();
                        BeanUtils.copyProperties(f, bean);
                        if (f.getId() != null) {
                            bean.setTrainningPlanName(eduTrainningPlanDao.getNameById(f.getTrainningPlanId()));
                            bean.setTrainningTypeName(commonTypeDao.getNameById(f.getTrainningTypeId()));
                        }
                        // bean.setTrainningDepartName(bpDepartDao.getNameById(f.getTrainningDepartId()));
                        // bean.setTrainningTe/edu/trainning-record/pageacherName(baseUserDao.getRealNameById(f.getTrainningTeacherId()));
                        // bean.setAssessDepartName(bpDepartDao.getNameById(f.getAssessDepartId()));
                        // bean.setExamName(eduExamDao.getNameById(f.getExamId()));
                        bean.setCertName(eduCertificateDao.getNameById(f.getCertId()));
                        Long recordId = f.getId();
                        List<EduTrainningRecordUser> recordUserList = eduTrainningRecordUserDao.findByTrainningRecordId(recordId);
                        long count = recordUserList.stream().filter(r -> Objects.isNull(r.getCertUserId())).count();
                        String examFlag = getExamFlag(f, recordUserList);
                        if (count > 0 && examFlag.equals("Y")) {
                            bean.setCertShow(1);
                        } else {
                            bean.setCertShow(0);
                        }
                        // bean.setCertShow(count > 0 ? 1 : 0);
                        long count1 = recordUserList.stream().filter(r -> Objects.nonNull(r.getCertUserId())).count();
                        bean.setCertRecordShow(count1 > 0 ? 1 : 0);
                        String deptName = bpDepartDao.getNameById(Long.valueOf(f.getResponsibleDept()));
                        bean.setResponsibleDeptName(deptName);
                        bean.setResponsibleDept(f.getResponsibleDept());
                        bean.setTrainingName(f.getTrainingName());
                        return bean;
                    }

                });
    }

    //考试结果-只要有一个人培训合格且没有发放证书返回Y,否则返回N
    private String getExamFlag(EduTrainningRecord f, List<EduTrainningRecordUser> recordUserList) {
        String flag = "N";
        for (EduTrainningRecordUser user : recordUserList) {
//            if (user.getScore() != null && f.getExamPassScore() != null && user.getScore() > f.getExamPassScore()) {
//                flag = "Y";
//                continue;
//            }
            //培训合格且没有发放
            if (StringUtils.isNotBlank(user.getTrainningResult()) && user.getTrainningResult().equals("Y")
                    && user.getCertUserId() == null) {
                flag = "Y";
                continue;
            }
        }
        return flag;
    }

    private Predicate prepareListSearchCondition(SearchEduTrainningRecord condition) {
        Predicate p = null;
        QEduTrainningRecord q = QEduTrainningRecord.eduTrainningRecord;
        if (condition.getCodeOrPlanName() != null) {
            List<Long> planIds = eduTrainningPlanDao.queryIdsByNameContain(condition.getCodeOrPlanName());
            if (CollectionUtils.isNotEmpty(planIds)) {
                p = ExpressionUtils.or(ExpressionUtils.or(q.code.contains(condition.getCodeOrPlanName()), q.trainingName.like("%"+condition.getCodeOrPlanName()+"%")),
                        ExpressionUtils.or(q.trainningPlanId.in(planIds), q.code.contains(condition.getCodeOrPlanName())));
            }else {
                p = ExpressionUtils.or(p, ExpressionUtils.or(q.code.contains(condition.getCodeOrPlanName()), q.trainingName.like("%"+condition.getCodeOrPlanName()+"%")));
            }

        }
        if (condition.getTrainningTypeId() != null) {
            p = ExpressionUtils.and(p, q.trainningTypeId.eq(condition.getTrainningTypeId()));
        }
        if (condition.getDepartId() != null) {
            p = ExpressionUtils.and(p, q.responsibleDept.eq(condition.getDepartId()));
        }
        if (condition.getStartTime() != null) {
            p = ExpressionUtils.and(p, q.trainningDate.goe(condition.getStartTime()));
        }
        if (condition.getEndTime() != null) {
            p = ExpressionUtils.and(p, q.trainningDate.loe(condition.getEndTime()));
        }
        return p;
    }

    @Override
    public void delete(Long id) throws BusinessRestrictionsException {
        // 校验业务逻辑是否允许删除。如本数据被其他业务关联，删除后导致其他业务不可用。不能删除时将抛出业务异常
        checkBussinessRestrictions(id);
        Optional<EduTrainningRecord> op = dao.findById(id);
        if (op.isPresent()) {
            Long planId = op.get().getTrainningPlanId();
            if (planId != null && planId > 0) {
                eduTrainningPlanService.updateTrainStatus(planId);
            }
            eduTrainningRecordCourseMapper.deleteCourseById(id);
            dao.deleteById(id);
        }
    }

    /**
     * 校验业务逻辑是否允许删除。如本数据被其他业务关联，删除后导致其他业务不可用
     *
     * @param id 要删除的业务ID
     */
    private void checkBussinessRestrictions(Long id) throws BusinessRestrictionsException {

    }

    @Override
    public EduTrainningRecord findById(Long id) {
        return dao.findById(id).orElse(null);
    }

    @Override
    public EduTrainningRecordDetailBean getById(Long id) {
        EduTrainningRecord entity = findById(id);
        if (entity == null) {
            return null;
        }
        EduTrainningRecordDetailBean bean = new EduTrainningRecordDetailBean();
        BeanUtils.copyProperties(entity, bean);
        bean.setTrainningPlanName(eduTrainningPlanDao.getNameById(entity.getTrainningPlanId()));
        bean.setTrainningTypeName(commonTypeDao.getNameById(entity.getTrainningTypeId()));
        bean.setTrainningDepartName(bpDepartDao.getNameById(entity.getTrainningDepartId()));
        bean.setTrainningTeacherName(baseUserDao.getRealNameById(entity.getTrainningTeacherId()));
        bean.setAssessDepartName(bpDepartDao.getNameById(entity.getAssessDepartId()));
        bean.setExamName(eduExamDao.getNameById(entity.getExamId()));
        bean.setCertName(eduCertificateDao.getNameById(entity.getCertId()));
        bean.setImages(findRecordImages(id));
        //bean.setUsers(findJoinInUsers(id, false, 0));
        bean.setUsers(findJoinTrainingUsers(id));
        String deptName = bpDepartDao.getNameById(Long.valueOf(entity.getResponsibleDept()));
        bean.setResponsibleDeptName(deptName);
        bean.setResponsibleDept(entity.getResponsibleDept());
        //查询附件信息
        if (entity.getAttachments()!=null) {
            List<BaseAttachmentBean> list = JSON.parseObject(entity.getAttachments(), List.class);
            bean.setAttachments(list);
        }
        bean.setExamMode(eduExamMapper.selectExamMode(entity.getExamId()));
        //培训对应的课程
        List<Long> courseIds= eduTrainningRecordCourseMapper.selectCourseIds(id);
        if (!CollectionUtil.isEmpty(courseIds)){
            bean.setCourseBeans(eduCourseMapper.selectBatchIds(courseIds));
        }
        return bean;
    }

    private List<EduExamUserScopeDetailBean> findJoinTrainingUsers(Long id) {
       return eduTrainningRecordUserMapper.selectUserByTrainingId(id);
    }

    @Override
    public EduTrainningRecordDetailVo findDetail(Long trainingRecordId) {
        EduTrainningRecord entity = findById(trainingRecordId);
        if (entity == null) {
            return null;
        }
        EduTrainningRecordDetailVo bean = new EduTrainningRecordDetailVo();
        BeanUtils.copyProperties(entity, bean);
        bean.setTrainningPlanName(eduTrainningPlanDao.getNameById(entity.getTrainningPlanId()));
        bean.setTrainningTypeName(commonTypeDao.getNameById(entity.getTrainningTypeId()));
        bean.setTrainningDepartName(bpDepartDao.getNameById(entity.getTrainningDepartId()));
        bean.setTrainningTeacherName(baseUserDao.getRealNameById(entity.getTrainningTeacherId()));
        bean.setAssessDepartName(bpDepartDao.getNameById(entity.getAssessDepartId()));
        if (entity.getExamId() != null){
            Optional<EduExam> optionalEduExam = eduExamDao.findById(entity.getExamId());
            if (optionalEduExam.isPresent()){
                EduExam eduExam = optionalEduExam.get();
                bean.setExamName(eduExam.getName());
                bean.setExamTime(eduExam.getStartTime());
                String typeName = commonTypeDao.getNameById(eduExam.getTypeId());
                bean.setExamType(typeName == null ? "" : typeName);
            }
        }
        bean.setCertName(eduCertificateDao.getNameById(entity.getCertId()));
        String deptName = bpDepartDao.getNameById(Long.valueOf(entity.getResponsibleDept()));
        bean.setResponsibleDeptName(deptName);
        bean.setResponsibleDept(entity.getResponsibleDept());
        return bean;
    }

    @Override
    public List<String> importTrainningRecord(MultipartFile file) {
        List<String> errorMessage = new ArrayList<>();
        try {
            XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
            List<EduTrainningRecord> list = new ArrayList<>();
            errorMessage = importData(workbook.getSheetAt(0), list);
            if (CollectionUtils.isEmpty(errorMessage)) {
                dao.saveAll(list);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return errorMessage;
    }

    private List<String> importData(XSSFSheet sheet, List<EduTrainningRecord> list) {
        List<String> errorMessage = new ArrayList<>();
        for (int i = 1; i < sheet.getLastRowNum()+1; i++) {
            EduTrainningRecord record = new EduTrainningRecord();
            XSSFRow row = sheet.getRow(i);
            if (row.getCell(0)!=null&&StringUtils.isBlank(getCellStringValue(row.getCell(0)))) {
                errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:培训名称不能为空", i + 1));
                return errorMessage;
            }
            record.setTrainingName(row.getCell(0).toString());

            if (row.getCell(1)!=null&&StringUtils.isNotBlank(getCellStringValue(row.getCell(1)))) {
                Long planId = eduTrainningPlanDao.findByCode(getCellStringValue(row.getCell(1)));
                if (planId == null) {
                    errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:培训计划编号不存在", i + 1));
                    return errorMessage;
                }
                record.setTrainningPlanId(planId);
            }
            if (row.getCell(3)!=null&&StringUtils.isBlank(getCellStringValue(row.getCell(3)))) {
                errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:培训类型不能为空", i + 1));
                return errorMessage;
            }
            XSSFCell cell3 = row.getCell(3);
            cell3.setCellType(CellType.STRING);
            CommonType type = commonTypeDao.findQuestionTypeAndName("培训计划", cell3.toString().trim());
            if (type == null) {
                errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:培训计划未找到", i + 1));
                return errorMessage;
            }
            record.setTrainningTypeId(type.getId());
            if (row.getCell(4)!=null&&StringUtils.isBlank(getCellStringValue(row.getCell(4)))) {
                errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:所属部门编码不能为空", i + 1));
                return errorMessage;
            }
            Long deptId = bpDepartDao.findIdByCode(getCellStringValue(row.getCell(4)));
            if (deptId == null) {
                errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:所属部门编码未找到", i + 1));
                return errorMessage;
            }
            record.setResponsibleDept(deptId.intValue());
            if (row.getCell(5)!=null&&StringUtils.isNotBlank(getCellStringValue(row.getCell(5)))) {
                Long dept = bpDepartDao.findIdByName(getCellStringValue(row.getCell(5)));
                if (dept == null) {
                    errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:所属部门未找到", i + 1));
                    return errorMessage;
                }
            }
            if (row.getCell(6)!=null&&StringUtils.isBlank(getCellStringValue(row.getCell(6)))) {
                errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:培训学时不能为空", i + 1));
                return errorMessage;
            }
            record.setLessons(Double.parseDouble(getCellStringValue(row.getCell(6))));

            if (row.getCell(7)!=null&&StringUtils.isNotBlank(getCellStringValue(row.getCell(7)))) {
                Date date = row.getCell(7).getDateCellValue();
                record.setTrainningDate(date);
            }
            if (row.getCell(8)!=null&&StringUtils.isNotBlank(getCellStringValue(row.getCell(8)))) {
                record.setTrainningPlace(getCellStringValue(row.getCell(8)));
            }

            if (row.getCell(9)!=null&&StringUtils.isNotBlank(getCellStringValue(row.getCell(9)))) {
                Long trainningDepartId = bpDepartDao.findIdByCode(getCellStringValue(row.getCell(9)));
                if (trainningDepartId == null) {
                    errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:培训单位编码未找到", i + 1));
                    return errorMessage;
                }
                record.setTrainningDepartId(trainningDepartId);
            }
            if (row.getCell(10)!=null&&StringUtils.isNotBlank(getCellStringValue(row.getCell(10)))) {
                Long dept = bpDepartDao.findIdByName(getCellStringValue(row.getCell(10)));
                if (dept == null) {
                    errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:培训单位名称未找到", i + 1));
                    return errorMessage;
                }
            }

            if (row.getCell(11)!=null&&StringUtils.isNotBlank(getCellStringValue(row.getCell(11)))) {
                Long assessDepartId = bpDepartDao.findIdByCode(getCellStringValue(row.getCell(11)));
                if (assessDepartId == null) {
                    errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:考核单位编码未找到", i + 1));
                    return errorMessage;
                }
                record.setAssessDepartId(assessDepartId);
            }
            if (row.getCell(12)!=null&&StringUtils.isNotBlank(getCellStringValue(row.getCell(12)))) {
                Long dept = bpDepartDao.findIdByName(getCellStringValue(row.getCell(12)));
                if (dept == null) {
                    errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:考核单位名称未找到", i + 1));
                    return errorMessage;
                }
            }

            if (row.getCell(13)!=null&&StringUtils.isNotBlank(getCellStringValue(row.getCell(13)))) {
                Double cost = Double.parseDouble(getCellStringValue(row.getCell(13)));
                record.setCost(cost);
            }
            if (row.getCell(14)!=null&&StringUtils.isNotBlank(getCellStringValue(row.getCell(14)))) {
                record.setIntroduction(getCellStringValue(row.getCell(14)));
            }
            String hasExam="N";
            if (row.getCell(15)!=null&&StringUtils.isNotBlank(getCellStringValue(row.getCell(15)))) {
                Long examId = eduExamDao.findByCode(getCellStringValue(row.getCell(15)));
                if (examId == null) {
                    errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:考试编码未找到", i + 1));
                    return errorMessage;
                }
                hasExam="Y";
                record.setExamId(examId);
            }
            record.setHasExam(hasExam);
            String hasCert="N";
            XSSFCell cell16 = row.getCell(16);
            if (row.getCell(16)!=null&&StringUtils.isNotBlank(getCellStringValue(row.getCell(16)))) {
                cell16.setCellType(CellType.STRING);
                Long eduCertificateId = eduCertificateDao.findByName(getCellStringValue(row.getCell(16)));
                if (eduCertificateId == null) {
                    errorMessage.add(String.format(sheet.getSheetName() + "第{%s}行:证书名称未找到", i + 1));
                    return errorMessage;
                }
                hasCert="Y";
                record.setCertId(eduCertificateId);
            }
            record.setHasCert(hasCert);
            record.setCode(bizCodeGeneratorFacade.peiXunJiLu());
            list.add(record);
        }
        return errorMessage;
    }

    @Override
    public List<String> importExcelData(MultipartFile file) throws Exception{
        XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
        List<String> messages = new ArrayList<>();
        if (workbook != null) {
            this.getSheetData(workbook.getSheetAt(0), messages);
        }
        return messages;
    }

    @Override
    public void oldData() {
        List<TrainningRelevanceDto> trainningRelevanceDtos = eduTrainningRecordMapper.selectTrainningRelevance();
        for (TrainningRelevanceDto trainningRelevanceDto : trainningRelevanceDtos) {
            if (!StringUtils.isEmpty(trainningRelevanceDto.getExamId())&&!StringUtils.isEmpty(trainningRelevanceDto.getCourseId())){
                //培训关联考试并关联课程 生成线上
                //System.out.println("关联考试并关联课程:"+trainningRelevanceDto.getTrainingId());
                EduTrainningRecord eduTrainningRecord = eduTrainningRecordMapper.selectById(trainningRelevanceDto.getTrainingId());
                eduTrainningRecord.setTrainingForm(TrainingFrom.ONLINE.getId());
                eduTrainningRecord.setTrainingQualifiedStandard(TrainingQualifiedStandard.FINISH_COURSE_EXAM.getId());
                eduTrainningRecordMapper.updateById(eduTrainningRecord);
                //取消考试关联课程表，转移到培训关联课程表中
                EduTrainningRecordCourse eduTrainningRecordCourse = new EduTrainningRecordCourse();
                eduTrainningRecordCourse.setTrainningRecordId(Long.valueOf(trainningRelevanceDto.getTrainingId()));
                eduTrainningRecordCourse.setCourseId(Long.valueOf(trainningRelevanceDto.getCourseId()));
                eduTrainningRecordCourse.setCreateTime(new Date());
                eduTrainningRecordCourse.setCreateBy(Context.getCurrentUserId());
                eduTrainningRecordCourseMapper.insert(eduTrainningRecordCourse);
            }else if (!StringUtils.isEmpty(trainningRelevanceDto.getExamId())&& StringUtils.isEmpty(trainningRelevanceDto.getCourseId())){
                //培训关联考试没有关联课程 生成线下 考试通过
               // System.out.println("关联考试没有关联课程:"+trainningRelevanceDto.getTrainingId());
                EduTrainningRecord eduTrainningRecord = eduTrainningRecordMapper.selectById(trainningRelevanceDto.getTrainingId());
                eduTrainningRecord.setTrainingForm(TrainingFrom.OFFLINE.getId());
                eduTrainningRecord.setTrainingQualifiedStandard(TrainingQualifiedStandard.PASS_EXAM.getId());
                eduTrainningRecordMapper.updateById(eduTrainningRecord);
            }else if (StringUtils.isEmpty(trainningRelevanceDto.getExamId())){
                //培训没有关联考试 生成线下 手动录入
               // System.out.println("培训没有关联考试:"+trainningRelevanceDto.getTrainingId());
                EduTrainningRecord eduTrainningRecord = eduTrainningRecordMapper.selectById(trainningRelevanceDto.getTrainingId());
                eduTrainningRecord.setTrainingForm(TrainingFrom.OFFLINE.getId());
                eduTrainningRecord.setTrainingQualifiedStandard(TrainingQualifiedStandard.MANUAL_ENTRY.getId());
                eduTrainningRecordMapper.updateById(eduTrainningRecord);
            }
        }

    }

    @Override
    public Object trainningRecordList(SearchEduTrainningRecord condition) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<EduTrainningRecord> eduTrainningRecordPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(condition.getPage()+1,condition.getSize());
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<EduTrainningRecordVo> page= eduTrainningRecordMapper.trainningRecordList(eduTrainningRecordPage,condition);
        List<EduTrainningRecordVo> records = page.getRecords();
        records.forEach(eduTrainningRecordVo -> {
            //沿用以前逻辑
            List<EduTrainningRecordUser> recordUserList = eduTrainningRecordUserDao.findByTrainningRecordId(eduTrainningRecordVo.getId());
            long count = recordUserList.stream().filter(r -> Objects.isNull(r.getCertUserId())).count();
            String examFlag = getExamFlag(null, recordUserList);
            if (count > 0 && examFlag.equals("Y")) {
                eduTrainningRecordVo.setCertShow(1);
            } else {
                eduTrainningRecordVo.setCertShow(0);
            }

            eduTrainningRecordVo.setTrainingFormName(TrainingFrom.findNameById(eduTrainningRecordVo.getTrainingForm()));
            eduTrainningRecordVo.setTrainingPublishStatusName(TrainingPublishStatus.findNameById(eduTrainningRecordVo.getTrainingPublishStatus()));
        });
        return ResultBean.pageData(records,page.getTotal());
    }

    @Override
    public Object trainingStatistics(SearchEduTrainningRecord condition) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<EduTrainningRecord> eduTrainningRecordPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(condition.getPage() + 1, condition.getSize());
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<EduTrainningRecordVo> trainningRecordVoPage=eduTrainningRecordMapper.trainingStatistics(eduTrainningRecordPage,condition);
        return ResultBean.pageData(trainningRecordVoPage.getRecords(),trainningRecordVoPage.getTotal());
    }

    @Override
    public void exportSignIn(Long id, HttpServletResponse response) {
        ServletOutputStream outStream = null;
        List<ExportSignInVo> list= eduTrainningRecordUserMapper.exportSignIn(id);
        if (list != null && list.size() > 0 ){
            for (int i = 0; i < list.size(); i++) {
                ExportSignInVo exportSignInVo = list.get(i);
                exportSignInVo.setSignName(TrainingUserSignStatus.findNameById(exportSignInVo.getHasSignIn()));
                exportSignInVo.setId(i+1);
            }
        }
        EduTrainningRecord eduTrainningRecord = eduTrainningRecordMapper.selectById(id);
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            TemplateExportParams params = new TemplateExportParams(
                    "template/training.xlsx");
            Map<String, Object> map = new HashMap<>();
            map.put("trainingName", eduTrainningRecord.getTrainingName());
            map.put("aList", list);
            Workbook workbook = ExcelExportUtil.exportExcel(params, map);
            response.setContentType("application/x-msdownload");
            response.setHeader("Content-disposition", "attachment; filename=" + java.net.URLEncoder.encode(eduTrainningRecord.getTrainingName()+"签到记录"+dateFormat.format(new Date()) + ".xlsx", "UTF-8"));
            outStream = response.getOutputStream();
            workbook.write(outStream);
            outStream.close();
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("导出失败");
        }
    }

    @Override
    public Object studentStatistics(SearchEduTrainningRecord condition) {
        Long examId= eduTrainningRecordMapper.selectExamIdByTrainingId(condition.getId());
        List<Long> courseIds = eduTrainningRecordCourseMapper.selectCourseIds(condition.getId());
        int coursewareCount =0;
        List<Long> coursewareIds=null;
        if (!CollectionUtil.isEmpty(courseIds)){
            coursewareIds = eduTrainningRecordCourseMapper.selectCoursewareCount(courseIds);
            coursewareCount = coursewareIds.size();
        }
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<EduTrainningRecord> eduTrainningRecordPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(condition.getPage() + 1, condition.getSize());
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<ExportSignInVo> exportSignInVoPage = eduTrainningRecordUserMapper.studentStatistics(eduTrainningRecordPage, condition, coursewareIds, coursewareCount,examId);
        return ResultBean.pageData(exportSignInVoPage.getRecords(),exportSignInVoPage.getTotal());
    }

    @Override
    public Object qrCodeValid(Long id) {
        Long currentUserId = Context.getCurrentUserId();
        EduTrainningRecord eduTrainningRecord = eduTrainningRecordMapper.selectById(id);
        Date now = new Date();
        if (eduTrainningRecord.getTrainingPublishStatus()==TrainingPublishStatus.UN_PUBLISH.getId()) {
            throw new IllegalArgumentException("培训还未发布，无法签到");
        } else if (now.after(eduTrainningRecord.getTrainningEndDate())) {
            throw new IllegalArgumentException("签到时间已过，无法签到");
        } else if (now.before(eduTrainningRecord.getTrainningDate())) {
            throw new IllegalArgumentException("培训还未开始，无法签到");
        } else if (DateUtil.isIn(now,eduTrainningRecord.getTrainningDate(),eduTrainningRecord.getTrainningEndDate())
        && eduTrainningRecord.getTrainingPublishStatus()==TrainingPublishStatus.PUBLISH.getId() ){
            //进行中和已发布 可以签到
            if (eduTrainningRecordUserMapper.selectByUserAndTrainingId(currentUserId,id)==0){
                throw new IllegalArgumentException("您无需参加当前培训");
            }
            //签到成功 修改签到状态
            eduTrainningRecordUserMapper.updateSignInStatus(currentUserId,id);
            List<Long> userIds=new ArrayList<>();
            userIds.add(currentUserId);
            //校验培训合格标准是否是完成签到
            if (TrainingQualifiedStandard.FINISH_SIGN_IN.getId()==eduTrainningRecord.getTrainingQualifiedStandard()){
                //修改培训结果为合格
                eduTrainningRecordUserMapper.updateTrainingResultByUserIds(id,"Y",userIds);
            }
            else if (TrainingQualifiedStandard.FINISH_SIGN_IN_EXAM.getId()==eduTrainningRecord.getTrainingQualifiedStandard()) {
                // 完成签到 考试是否通过
                if (!ObjectUtils.isEmpty(eduTrainningRecord.getExamId())) {
                    if (eduExamMapper.selectPassExam(currentUserId, eduTrainningRecord.getExamId()) > 0) {
                        eduTrainningRecordUserMapper.updateTrainingResultByUserIds(id, "Y", userIds);
                    }
                }
            }
//            }else if (TrainingQualifiedStandard.PASS_EXAM.getId()==eduTrainningRecord.getTrainingQualifiedStandard()){
//                if (eduExamMapper.selectPassExam(currentUserId,eduTrainningRecord.getExamId())>0){
//                    eduTrainningRecordUserMapper.updateTrainingResultByUserIds(id,"Y",userIds);
//                }else {
//                    eduTrainningRecordUserMapper.updateTrainingResultByUserIds(id,"N",userIds);
//                }
//            }
            if (eduTrainningRecord.getOpenFace()==TrainingOpenFace.OPEN_FACE.getId()){
                return ResultBean.success(TrainingOpenFace.OPEN_FACE.getId(),"签到成功");
            }
            return ResultBean.success(TrainingOpenFace.UN_OPEN_FACE.getId(),"签到成功");
        }else {
            throw new IllegalArgumentException("请扫描正确的二维码");
        }
    }

    @Override
    public Object saveTrainingResult(SearchEduTrainningRecord condition) {
        if (CollectionUtil.isEmpty(condition.getUserIds())){
            throw new IllegalArgumentException("培训人员不能为空");
        }
        if (!"Y".equals(condition.getTrainingResult()) && !"N".equals(condition.getTrainingResult())) {
            throw new IllegalArgumentException("培训结果只能为Y或N");
        }
        eduTrainningRecordUserMapper.updateTrainingResultByUserIds(condition.getId(),condition.getTrainingResult(),condition.getUserIds());
        return ResultBean.success("");
    }

    @Override
    public void exportStudentStatistics(SearchEduTrainningRecord condition,HttpServletResponse response) {
        condition.setSize(Integer.MAX_VALUE);
        ServletOutputStream outStream = null;
        ResultBean resultBean = (ResultBean) this.studentStatistics(condition);
        List<ExportSignInVo> list = (List<ExportSignInVo>) resultBean.getData();
        EduTrainningRecord eduTrainningRecord = eduTrainningRecordMapper.selectById(condition.getId());
        for (int i = 0; i < list.size(); i++) {
            ExportSignInVo exportSignInVo = list.get(i);
            exportSignInVo.setId(i+1);
        }
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            TemplateExportParams params = new TemplateExportParams(
                    "template/trainingStudentChart.xlsx");
            Map<String, Object> map = new HashMap<>();
            map.put("list", list);
            map.put("trainingName", eduTrainningRecord.getTrainingName());
            Workbook workbook = ExcelExportUtil.exportExcel(params, map);
            response.setContentType("application/x-msdownload");
            response.setHeader("Content-disposition", "attachment; filename=" + java.net.URLEncoder.encode(eduTrainningRecord.getTrainingName()+"学员统计"+dateFormat.format(new Date()) + ".xlsx", "UTF-8"));
            outStream = response.getOutputStream();
            workbook.write(outStream);
            outStream.close();
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("导出失败");
        }
    }

    @Override
    public ResultBean myTrainingList(SearchEduTrainningRecord condition) {
        if (!StringUtils.isEmpty(condition.getTrainingResult())){
            if (!"Y".equals(condition.getTrainingResult()) && !"N".equals(condition.getTrainingResult())) {
                throw new IllegalArgumentException("培训结果只能为Y或N");
            }
        }
        condition.setUserId(Context.getCurrentUserId());
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<EduTrainningRecord> eduTrainningRecordPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(condition.getPage()+1, condition.getSize());
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<MyTrainingAppVo> page= eduTrainningRecordMapper.myTrainingList(eduTrainningRecordPage,condition);
        List<MyTrainingAppVo> records = page.getRecords();
        return ResultBean.pageData(records,page.getTotal());
    }


    @Override
    public ResultBean myTrainingDetails(Long trainingId) {
        Long currentUserId = Context.getCurrentUserId();
        TrainingAppDetailsVo.TrainingUserDetails trainingUserDetails = new TrainingAppDetailsVo.TrainingUserDetails();
        TrainingAppDetailsVo trainingAppDetailsVo=eduTrainningRecordMapper.selectDetailsByTrainingId(trainingId);
        //培训需要签到
        if (TrainingUserSignStatus.OFFLINE.getId()==trainingAppDetailsVo.getHasSignIn()){
            trainingUserDetails.setHasSignIn(eduTrainningRecordUserMapper.queryRecordsByUserIdAndTrainingId(trainingId,currentUserId));
        }
        if (!ObjectUtils.isEmpty(trainingAppDetailsVo.getExamId())){
            //关联考试
            SearchEduTrainningRecord condition = new SearchEduTrainningRecord();
            condition.setUserId(currentUserId);
            condition.setExamId(trainingAppDetailsVo.getExamId());
            com.baomidou.mybatisplus.extension.plugins.pagination.Page<EduExam> eduExamPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(condition.getPage(), condition.getSize());
            com.baomidou.mybatisplus.extension.plugins.pagination.Page<ExamUserVo> examUserVoPage = eduExamMapper.myExamList(eduExamPage, condition);
            condition=null;
            List<ExamUserVo> records = examUserVoPage.getRecords();
            ExamUserVo examUserVo =null;
            if (!CollectionUtil.isEmpty(records)){
                examUserVo =records.get(0);
                examUserVo.setFormTypeName(TrainingFrom.findNameById(examUserVo.getFormType()));
                trainingAppDetailsVo.setExamUserVo(examUserVo);
            }

        }
        List<CourseVo> courseVos = eduTrainningRecordCourseMapper.selectCourseList(trainingId);
        Pageable pageable = PageRequest.of(0, Integer.MAX_VALUE);
        courseVos.forEach(courseVo -> {
            Page<EduCoursewareDetailBean> coursecenterPage = eduCoursewareService.findCoursecenterPage(courseVo.getCourseId(), null, pageable);
            courseVo.setCoursewareVos(coursecenterPage.getContent());
        });

        //培训活动下的课程
        trainingAppDetailsVo.setCourseVos(courseVos);
        //培训活动下的课件
        List<Long> trainingCoursewares= eduTrainningRecordMapper.selectCoursewareByTrainingId(trainingId);
        //用户学习过的课件 已完成
        List<Long> learns=eduTrainningRecordUserMapper.selectUserLearnCourseware(currentUserId,trainingCoursewares,1,trainingId);
        //用户学习过的课件 未学完
        List<Long> unLearns=eduTrainningRecordUserMapper.selectUserLearnCourseware(currentUserId,trainingCoursewares,0,trainingId);
        unLearns.removeAll(learns);
        trainingUserDetails.setUnFinishCoursewareIds(unLearns);
        trainingUserDetails.setFinishCoursewareIds(learns);
        trainingAppDetailsVo.setTrainingUserDetails(trainingUserDetails);
        return ResultBean.success(trainingAppDetailsVo);
    }

    /**
     * 发布或取消
     * @param condition
     */
    @Override
    public void trainningPublish(SearchEduTrainningRecord condition){

        EduTrainningRecord eduTrainningRecord = eduTrainningRecordMapper.selectById(condition.getId());
        eduTrainningRecord.setTrainingPublishStatus(condition.getStatus());
        eduTrainningRecordMapper.updateById(eduTrainningRecord);
        if (eduTrainningRecord.getExamId()!=null){
            EduExam eduExam = eduExamMapper.selectById(eduTrainningRecord.getExamId());
            eduExam.setState(condition.getStatus());
            if (condition.getStatus()==TrainingPublishStatus.PUBLISH.getId()){
                //培训发布修改考试发布时间
                eduExam.setReleaseTime(new Date());
            }else {
                eduAsyncService.deleteRedisKeyByExamId(eduTrainningRecord.getExamId());
            }
            eduExamMapper.updateById(eduExam);
        }
        // 发送发布消息通知
        eduAsyncService.saveToTriggerTraining(eduTrainningRecord,condition.getId(),new CommonBean());
    }
//
//    private Set<Long> getUsersIds(Long id) {
//        List<EduTrainningRecordUser> recordUsers = eduTrainningRecordUserMapper
//                .selectList(new LambdaQueryWrapper<EduTrainningRecordUser>()
//                .eq(EduTrainningRecordUser::getTrainningRecordId, id)
//                .eq(EduTrainningRecordUser::getDeleteFlag,"0"));
//        Set<Long> set = new HashSet<>();
//        if (!CollectionUtil.isEmpty(recordUsers)){
//            for (EduTrainningRecordUser recordUser : recordUsers) {
//                set.add(recordUser.getUserId());
//            }
//        }
//        return set;
//    }

//
//    public void saveToTrigger(EduTrainningRecord eduTrainningRecord,Set<Long> users) throws ApiBusinessException {
//        BaseConfig trainningConfig = baseConfigService.findFirstConfig(BaseConfigCodes.GETUI_TRAINNING_NOTIFICATION_CONTENT);
//        BaseConfig examConfig = baseConfigService.findFirstConfig(BaseConfigCodes.GETUI_EXAM_PUBLISH_NOTIFICATION_CONTENT);
//        BaseConfig notificationTitle = baseConfigService.findFirstConfig(BaseConfigCodes.GETUI_EXAM_NOTIFICATION_TITLE);
//        BaseConfig cancelConfig = baseConfigService.findFirstConfig(BaseConfigCodes.GETUI_EXAM_CANCEL_NOTIFICATION_CONTENT);
//        if (notificationTitle == null ||trainningConfig ==null ||examConfig==null ||cancelConfig==null ) {
//            throw new ApiBusinessException(Status.NOTICE_NOT_CONFIGURATION_PARAM);
//        }
//
//        String trainningMsgBody = String.format(trainningConfig.getValue(), TrainingFrom.findNameById(eduTrainningRecord.getTrainingForm()),eduTrainningRecord.getTrainingName(),SimpleDateFormatCache.getYmdhm().format(eduTrainningRecord.getTrainningDate()));
//        EduExam eduExam = eduExamMapper.selectById(eduTrainningRecord.getExamId());
//        String examMsgBody="";
//        if (!ObjectUtils.isEmpty(eduExam)){
//             examMsgBody = String.format(examConfig.getValue(), TrainingFrom.findNameById(Math.toIntExact(eduExam.getFormType())),eduExam.getName(),SimpleDateFormatCache.getYmdhm().format(eduTrainningRecord.getTrainningDate()));
//        }
//        String msgTitle = notificationTitle.getValue();
//        String cancelMsg = cancelConfig.getValue();
//
//        if (eduTrainningRecord.getTrainingForm()==TrainingFrom.ONLINE.getId()){
//            //线下通知培训人员和讲师
//            users.add(eduTrainningRecord.getTrainningTeacherId());
//        }
//        //发布状态
//        if (eduTrainningRecord.getTrainingPublishStatus()==TrainingPublishStatus.PUBLISH.getId()){
//            alertMessageService.pushSingleBatchCid(users, msgTitle, trainningMsgBody, null, true);
//            //向web端发送培训发布通知
//            commonIndexNotifyService.releaseExamReminder(users, eduTrainningRecord.getId(), msgTitle, eduTrainningRecord.getTrainningDate(), trainningMsgBody);
//            //发布培训通知
//            generateAppNotify(users,trainningMsgBody,eduTrainningRecord.getId());
//             if (eduTrainningRecord.getExamId()!=null){
//                alertMessageService.pushSingleBatchCid(users, msgTitle, examMsgBody, null, true);
//                //向web端发送考试发布通知
//                commonIndexNotifyService.releaseExamReminder(users, eduTrainningRecord.getExamId(), msgTitle, eduTrainningRecord.getTrainningDate(), examMsgBody);
//                //如果关联考试再发布考试通知
//                generateAppExamNotify(users,examMsgBody,eduTrainningRecord.getExamId());
//            }
//        }else {
//            //取消通知
//            String cancelTrainning = String.format(cancelMsg, eduTrainningRecord.getTrainingName());
//            alertMessageService.pushSingleBatchCid(users, msgTitle, cancelTrainning, null, true);
//            //向web端发送培训取消通知
//            commonIndexNotifyService.releaseExamReminder(users, eduTrainningRecord.getId(), msgTitle, eduTrainningRecord.getTrainningDate(), cancelTrainning);
//            generateAppNotify(users,cancelTrainning,eduTrainningRecord.getId());
//            if (eduTrainningRecord.getExamId()!=null) {
//                //如果关联考试再发布取消考试通知
//                String cancelExam = String.format(cancelMsg, eduExam.getName());
//                alertMessageService.pushSingleBatchCid(users, msgTitle, cancelExam, null, true);
//                commonIndexNotifyService.releaseExamReminder(users, eduTrainningRecord.getId(), msgTitle, eduTrainningRecord.getTrainningDate(), cancelExam);
//                generateAppExamNotify(users,cancelExam,eduTrainningRecord.getExamId());
//            }
//        }
//    }
//    private void generateAppExamNotify(Set<Long> users, String examMsgBody, Long examId) {
//        ArrayList<CommonBusinessNotice> commonBusinessNotices = new ArrayList<>();
//        for (Long userId : users) {
//            String msgBody = MessageFormat.format(examMsgBody, baseUserDao.getRealNameById(userId));
//            CommonBusinessNotice appNotify = new CommonBusinessNotice();
//            appNotify.setBusinessType(AppBusinessNoticeTypes.EDU.getType())
//                    .setNoticeContent(msgBody)
//                    .setNoticeUser(userId)
//                    .setNoticeTitle(AppNotifyContentPre.EDU_NOTIFY)
//                    .setSendTime(new Date())
//                    .setRefId(examId);
//            commonBusinessNotices.add(appNotify);
//        }
//        commonBusinessNoticeService.saveBatch(commonBusinessNotices);
//    }
//
//    private void generateAppNotify(Set<Long> userIds,String msg,Long trainningId) {
//        // app通知中心
//        ArrayList<CommonBusinessNotice> commonBusinessNotices = new ArrayList<>();
//        for (Long userId : userIds) {
//            String msgBody = MessageFormat.format(msg, baseUserDao.getRealNameById(userId));
//            CommonBusinessNotice appNotify = new CommonBusinessNotice();
//            appNotify.setBusinessType(AppBusinessNoticeTypes.EDU.getType())
//                    .setNoticeContent(msgBody)
//                    .setNoticeUser(userId)
//                    .setNoticeTitle(AppNotifyContentPre.TRAINNING_NOTIFY)
//                    .setSendTime(new Date())
//                    .setRefId(trainningId);
//            commonBusinessNotices.add(appNotify);
//        }
//        commonBusinessNoticeService.saveBatch(commonBusinessNotices);
//    }

    private List<String> getSheetData(XSSFSheet sheet, List<String> messages) throws Exception {
        XSSFRow row;
        //第一行确定培训编号所在列
        row = sheet.getRow(0);
        Integer codeIndex = null;
        Integer nameIndex = null;
        Integer userCodeIndex = null;
        Integer userNameIndex = null;
        Integer resultIndex = null;
        Integer effectIndex = null;
        Integer userContractorFlagIndex = null;
        for (int j = 0; j < row.getLastCellNum(); j++) {
            if (row.getCell(j) != null && row.getCell(j).toString().equalsIgnoreCase("培训编号")) {
                codeIndex = j;
            }
            if (row.getCell(j) != null && row.getCell(j).toString().equalsIgnoreCase("培训名称")) {
                nameIndex = j;
            }
            if (row.getCell(j) != null && row.getCell(j).toString().equalsIgnoreCase("参加人员编号")) {
                userCodeIndex = j;
            }
            if (row.getCell(j) != null && row.getCell(j).toString().equalsIgnoreCase("参加人员姓名")) {
                userNameIndex = j;
            }
            if (row.getCell(j) != null && row.getCell(j).toString().equalsIgnoreCase("培训结果")) {
                resultIndex = j;
            }
            if (row.getCell(j) != null && row.getCell(j).toString().equalsIgnoreCase("效果评估")) {
                effectIndex = j;
            }
            if (row.getCell(j) != null && row.getCell(j).toString().equalsIgnoreCase("人员类型")) {
                userContractorFlagIndex = j;
            }
        }
        String code = null;
        String name = null;
        String userCode = null;
        String userName = null;
        String result = null;
        String effect = null;
        String userContractorFlag = null;
        Integer userFlag = null;
        List<EduTrainningRecordResultVo> list = Lists.newArrayList();
        String orgCode = Context.getCurrentOrgCode();
        Long tenantId = Context.getCurrentTenantId();
        Long userId = Context.getCurrentUserId();
        for (int i = 1; i < sheet.getLastRowNum() + 1; i++) {
            row = sheet.getRow(i);
            EduTrainningRecordResultVo vo = new EduTrainningRecordResultVo();
            String fields = "";
            try {
                if (codeIndex != null && row.getCell(codeIndex) != null) {
                    code = this.getCellStringValue(row.getCell(codeIndex));
                }
                if (nameIndex != null && row.getCell(nameIndex) != null) {
                    name = this.getCellStringValue(row.getCell(nameIndex));
                }
                if (userCodeIndex != null && row.getCell(userCodeIndex) != null) {
                    userCode = this.getCellStringValue(row.getCell(userCodeIndex));
                }
                if (userNameIndex != null && row.getCell(userNameIndex) != null) {
                    userName = this.getCellStringValue(row.getCell(userNameIndex));
                }
                if (resultIndex != null && row.getCell(resultIndex) != null) {
                    result = this.getCellStringValue(row.getCell(resultIndex));
                }
                if (effectIndex != null && row.getCell(effectIndex) != null) {
                    effect = this.getCellStringValue(row.getCell(effectIndex));
                }
                if (userContractorFlagIndex != null && row.getCell(userContractorFlagIndex) != null) {
                    userContractorFlag = this.getCellStringValue(row.getCell(userContractorFlagIndex));
                }
                if (StringUtils.isBlank(userContractorFlag)){
                    fields = fields+" 人员类型 ";
                }else {
                    if (CertificateUserTypes.findByName(userContractorFlag) == null){
                        fields = fields+" 人员类型 ";
                    }else {
                        userFlag = CertificateUserTypes.findByName(userContractorFlag).getCode();
                    }
                }
                if (StringUtils.isBlank(code)){
                    fields = fields+" 培训编号 ";
                }else {
                    if (isNum(code)){
                        code = getNumberString(code);
                    }
                    EduTrainningRecord record = dao.findByCode(code);
                    if (record == null){
                        fields = fields+" 培训编号 ";
                    }else {
                        vo.setTrainningRecordId(record.getId());
                        vo.setExamId(record.getExamId());
                    }
                }
                if (StringUtils.isBlank(userCode)){
                    fields = fields+" 参加人员编号 ";
                }else {
                    if (isNum(userCode)){
                        userCode = getNumberString(userCode);
                    }
                    if (userFlag == null){
                        fields = fields+" 人员类型 ";
                    }else {
                        if (userFlag.equals(CertificateUserTypes.USER.getCode())){
                            BaseUser user = baseUserDao.findByCode(userCode);
                            if (user == null){
                                fields = fields+" 参加人员编号 ";
                            }else {
                                vo.setUserId(user.getId());
                                //查询部门
                                vo.setDepartId(user.getDepartId());
                                vo.setDepartName(bpDepartDao.findDepartNameById(user.getDepartId()));
                            }
                        }else {
                            //查询承包商
                            Long staffUserId = bpContractorStaffDao.findStaffByCode(userCode);
                            if (staffUserId == null){
                                fields = fields+" 参加人员编号 ";
                            }else {
                                vo.setUserId(staffUserId);
                            }
                        }
                    }

                }
                if (StringUtils.isBlank(result)){
                    fields = fields+" 培训结果 ";
                }else {
                    if (!"合格".equals(result) && !"不合格".equals(result)){
                        fields = fields+" 培训结果 ";
                    }
                }
                if (StringUtils.isNotBlank(effect) && QualifiedTypes.findByName(effect) == null){
                    fields = fields+" 效果评估 ";
                }
                if (StringUtils.isNotBlank(fields)){
                    messages.add("第" + (i + 1) + "行,"+fields+"字段数据有误");
                }else {
                    if (QualifiedTypes.findByName(effect)!=null){
                        vo.setEvaluation(QualifiedTypes.findByName(effect).getCode());
                    }
                    vo.setUserContractorFlag(userFlag);
                    vo.setName(name);
                    vo.setCode(code);
                    vo.setTrainningResult(result);
                    vo.setUserName(userName);
                    vo.setUserCode(userCode);
                    list.add(vo);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (CollectionUtils.isEmpty(messages)){
            List<EduTrainningRecordUser> users = Lists.newArrayList();
            list.forEach(vo->{
                EduTrainningRecordUser recordUser = eduTrainningRecordUserDao.getEduTrainingRecordUser(vo.getTrainningRecordId(),vo.getUserId());
                if (recordUser == null){
                    recordUser = new EduTrainningRecordUser();
                    recordUser.setTrainningRecordId(vo.getTrainningRecordId());
                    recordUser.setUserId(vo.getUserId());
                    recordUser.setOrgCode(orgCode);
                    recordUser.setTenentId(tenantId);
                    recordUser.setUpdateBy(userId);
                    recordUser.setDeleteFlag(DeleteFlag.EFFECTIVE.getCode());
                    recordUser.setUserContractorFlag(vo.getUserContractorFlag());
                }
                //查询成绩
                EduExamRecord record = eduExamRecordDao.selectByUserIdAndExamIdLatest(vo.getUserId(),vo.getExamId());
                if (record != null){
                    recordUser.setScore(record.getScore());
                }
                recordUser.setEvaluation(vo.getEvaluation());
                recordUser.setTrainningResult(vo.getTrainningResult().equals("合格")?"Y":"N");
                recordUser.setDepartName(vo.getDepartName());
                recordUser.setDepartId(vo.getDepartId());
                users.add(recordUser);
            });
            eduTrainningRecordUserDao.saveAll(users);
        }
        return messages;
    }

    public String getNumberString(String str) {
        if (str.equals("0.0")) {
            return "0";
        }
        if (str.startsWith("0") || str.length() > 512) {
            return str;
        }
        Double d = Double.valueOf(str);
        NumberFormat nf = NumberFormat.getInstance();
        String s = nf.format(d);
        if (s.indexOf(",") >= 0) {
            s = s.replace(",", "");
        }
        return s;
    }

    public Boolean isNum(String str) {
        try {
            new Float(str);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public String getCellStringValue(XSSFCell cell) {
        Object obj = getCellValue(cell, true);
        return obj == null ? null : obj.toString().trim();
    }

    private Object getCellValue(XSSFCell cell, boolean isText) {
        CellType cellType = cell.getCellType();
        DecimalFormat df = new DecimalFormat("0");


        Object value = null;
        switch (cellType) {
            case STRING: {
                value = cell.getStringCellValue();
                break;
            }
            case NUMERIC: {
                value = cell.getNumericCellValue();
                if (isText) {
                    BigDecimal decimal = new BigDecimal(value.toString());
                    int scale = decimal.scale();
                    if (scale < 1) {
                        //小于1代表科学计数或者整数
                        value = df.format(decimal);
                    } else {
                        value = String.valueOf(decimal);
                    }
                    return String.valueOf(value);
                }
                break;
            }
            case FORMULA: {
                value = cell.getNumericCellValue();
                if (isText) {
                    return value.toString();
                }
                break;
            }
        }
        return value;
    }

    @Override
    public List<EduTrainningRecordUserDetailBean> findJoinInUsersById(Long id) {
        return findJoinInUsers(id, true, 1);
    }

    @Override
    public List<EduTrainningRecordUserDetailBean> certRecord(Long id) {
        return findJoinInUsers(id, true, 2);
    }

    //flag,  0 :getById显示所有    1: 发送证书   2: 发放证书记录
    private List<EduTrainningRecordUserDetailBean> findJoinInUsers(Long id, boolean lookupCertRecord, Integer flag) {
        EduTrainningRecord one = dao.getOne(id);

        List<EduTrainningRecordUser> users = eduTrainningRecordUserDao.findByTrainningRecordId(id);
        if (flag == 1) {
            //发放证书只显示没发放的人员
            users = users.stream().filter(r -> Objects.isNull(r.getCertUserId())).collect(Collectors.toList());
        } else if (flag == 2) {
            //证书记录只有已发放的才显示
            users = users.stream().filter(r -> Objects.nonNull(r.getCertUserId())).collect(Collectors.toList());
        }


        // e is EduTrainningRecordUser
        List<EduTrainningRecordUserDetailBean> result = users.stream().map(e -> {
            EduTrainningRecordUserDetailBean bean = new EduTrainningRecordUserDetailBean();
            BeanUtils.copyProperties(e, bean);
            bean.setEvaluation(bean.getEvaluation());
            bean.setTrainningResult(bean.getTrainningResult());

            bean.setCertId(one.getCertId());
            Long userId = e.getUserId();
            bean.setUserId(userId);
            Integer userContractorFlag = e.getUserContractorFlag();
            bean.setUserContractorFlag(userContractorFlag);
            if (userContractorFlag == null || userContractorFlag == 0) {
                BaseUser user = baseUserDao.findById(userId).get();
                bean.setUserName(user.getRealName());
                bean.setCompanyId(Context.getCompanyId());
                bean.setCompanyName(Context.getCompanyName());
                if (user.getJob()!=null) {
                bean.setJobName(jobDao.findNameById(user.getJob()));
                }
            } else {
                BpContractorStaff staff = bpContractorStaffService.getById(userId);
                if (staff != null) {
                    bean.setUserName(staff.getName());
                    Long contractorId = staff.getContractorId();
                    BpContractor bpContractor = bpContractorService.get(contractorId);
                    if (bpContractor != null) {
                        bean.setCompanyId(contractorId);
                        bean.setCompanyName(bpContractor.getCompanyName());
                    }
                }
            }

            return bean;
        }).collect(Collectors.toList());
        if ("Y".equals(one.getHasExam())) {
            Float passScore = eduExamDao.sumPassScore(one.getExamId());
            result.forEach(detail -> {
                detail.setPassScore(passScore);
            });
            // #1 EduTrainningRecordUser虽然带了score信息，但是仍然需要查询，EduTrainningRecordUser生成后，用户可能考试了，实时查询更准确
            // #2 #1存在不合理，应以填写培训记录时的成绩为准，后续考试的成绩应该不算，否则会造成干扰。培训记录时没有考试成绩，后续考试，过了，却没有证书
            // completeUserExamInfo(one.getExamId(), result);
        }
        if ("Y".equals(one.getHasCert())) {
            completeCertInfo(one.getCertId(), result);
        }
        if (lookupCertRecord) {
            // 查询本次获取的证书情况
            completeUserCertInfo(result);
        }
        return result;
    }

    private void completeCertInfo(Long certId, List<EduTrainningRecordUserDetailBean> result) {
        eduCertificateDao.findById(certId).ifPresent(cert -> {
            result.forEach(detail -> {
                detail.setCertName(cert.getName());
            });
        });
    }

    private void completeUserExamInfo(Long examId, List<EduTrainningRecordUserDetailBean> result) {
        List<Long> userIds = result.stream().map(EduTrainningRecordUserDetailBean::getUserId)
                .collect(Collectors.toList());
        System.out.println(examId + ":" + userIds);
        List<EduExamRecord> examRecords = eduExamRecordDao.findByExamIdAndUserIdIn(examId, userIds);
        if (examRecords.isEmpty()) {
            return;
        }
        // e is EduTrainningRecordUserDetailBean
        result.forEach(detail -> {
            EduExamRecord record = findExamRecord(detail.getUserId(), examRecords);
            if (record != null) {
                detail.setPassScore(record.getPassScore());
                detail.setScore(record.getScore());
            }
        });
    }

    /**
     * 填充用户参与培训取得的证书情况
     *
     * @param result
     */
    private void completeUserCertInfo(List<EduTrainningRecordUserDetailBean> result) {
        List<Long> userCertIds = result.stream().map(EduTrainningRecordUserDetailBean::getCertUserId)
                .filter(Objects::nonNull).collect(Collectors.toList());
        List<EduCertificateUser> ids = eduCertificateUserDao.findAllById(userCertIds);
        if (ids.isEmpty()) {
            return;
        }
        result.forEach(e -> {
            EduCertificateUser record = findUserCert(e.getCertUserId(), ids);
            if (record != null) {
                e.setCertNo(record.getCertNo());
                e.setTakenDate(record.getTakenTime());
                e.setGranted(StringUtils.isNoneBlank(record.getCertNo()));
            }
        });
    }

    private EduCertificateUser findUserCert(Long certUserId, List<EduCertificateUser> ids) {
        for (EduCertificateUser e : ids) {
            if (Objects.equals(certUserId, e.getId())) {
                return e;
            }
        }
        return null;
    }

    private EduExamRecord findExamRecord(Long id, List<EduExamRecord> records) {
        for (EduExamRecord record : records) {
            if (record.getUserId().equals(id)) {
                return record;
            }
        }
        return null;
    }

    private List<BaseAttachmentBean> findRecordImages(Long id) {
        List<EduTrainningRecordImage> images = eduTrainningRecordImageDao.findByTrainningRecordId(id);
        return images.stream().map(e -> {
            return baseImageRespositoryService.findBeanById(e.getImageId());
        }).collect(Collectors.toList());
    }

    @Override
    public void awardUserCerts(List<EduTrainningRecordUserDetailBean> awards) {
        if (awards == null || awards.isEmpty()) {
            return;
        }

        int i = 0;
        for (EduTrainningRecordUserDetailBean bean : awards) {
            if (bean.getTakenDate() == null && StringUtils.isBlank(bean.getCertNo())) {
                i++;
            }
        }
        if (awards.size() == i) {
            throw new IllegalArgumentException("作业编号和取证日期不能都为空");
        }

        List<Long> recordIdList = awards.stream().map(EduTrainningRecordUserDetailBean::getId)
                .collect(Collectors.toList());

        List<EduTrainningRecordUser> records = eduTrainningRecordUserDao.findAllById(recordIdList);

        // 保存二者之间的关系
        Map<Long, EduCertificateUser> recordIdToCertMap = new HashMap<>();
        List<EduCertificateUser> list = awards.stream().map(e -> {
            // 给此人颁发了证书
            if (StringUtils.isBlank(e.getCertNo()) && e.getTakenDate() != null) {
                throw new IllegalArgumentException("培训证书号不能为空");
            }
            if (StringUtils.isNotBlank(e.getCertNo()) && e.getTakenDate() == null) {
                throw new IllegalArgumentException("取证日期不能为空");
            }
            LambdaQueryWrapper<WwytEduCertificateUser> repeat = new QueryWrapper<WwytEduCertificateUser>().lambda()
                    .eq(WwytEduCertificateUser::getCertId, e.getCertId())
                    .eq(WwytEduCertificateUser::getCertNo, e.getCertNo())
                    .eq(WwytEduCertificateUser::getDeleteFlag, "0");
            Integer count = wwytEduCertificateUserMapper.selectCount(repeat);
            if (count > 0) {
                throw new IllegalArgumentException("证书编号重复! 一个证书种类的只能有一个唯一编号!");
            }
            EduCertificateUser cert = null;
            //EduCertificate certificate = eduCertificateDao.getOne(e.getCertId());
            if (e.getCertUserId() != null) {
                // 已经有证书
                cert = eduCertificateUserDao.findById(e.getCertUserId()).orElse(null);
            } else if (StringUtils.isNotBlank(e.getCertNo())) {
                // 新增证书
                cert = new EduCertificateUser();
                cert.setCertId(e.getCertId());
                cert.setUserId(e.getUserId());
                cert.setUserContractorFlag(e.getUserContractorFlag());
            }
            if (cert != null) {
                cert.setCertificateStatus(1);
                cert.setCertNo(e.getCertNo());
                cert.setTakenTime(e.getTakenDate());
                /*if (e.getTakenDate() != null) {
                    cert.setOutOfDateTime(calculateOutofDateTime(e.getTakenDate(), certificate));
                }*/
                recordIdToCertMap.put(e.getId(), cert);
            }
            return cert;
        }).filter(Objects::nonNull).collect(Collectors.toList());
        // 保存/更新
        eduCertificateUserDao.saveAll(list);

        // 更新培训记录关联的证书
        updateRecordCertInfo(records, recordIdToCertMap);
    }

    @Override
    public ResultBean userInfoTrain(Long userId, Pageable pageable, Integer userContractorFlag) {
        userContractorFlag = userContractorFlag == null ? 0 : userContractorFlag;
        Page<EduTrainUserInfoDto> page = dao.userInfoTrain(userId, pageable, userContractorFlag);
        return ResultBean.pageData(page.getContent(), page.getTotalElements());
    }

    /**
     *根据条件获取培训记录学时
     * @param eduTrainTimeBean
     * @return
     */
    @Override
    public IPage<EduTrainningRecordUser> getUserTrainTime(EduTrainTimeBean eduTrainTimeBean,Integer pageNo,Integer pageSize) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<EduTrainningRecordUser> eduTrainningRecordUserPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNo, pageSize);
        List<EduTrainningRecordUser> eduTrainningRecordUserList = new ArrayList<>();
        Long userId = eduTrainTimeBean.getUserId();
        Long departId = eduTrainTimeBean.getDepartId();
        Long jobId = eduTrainTimeBean.getJobId();
        //设置默认日期
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.add(Calendar.MONTH, 0);
        Date beginTime = calendar.getTime();
        if (eduTrainTimeBean.getBeginTime() != null) {
            beginTime = eduTrainTimeBean.getBeginTime();
        }
        Date endTime = new Date();
        if (eduTrainTimeBean.getEndTime() != null) {
            endTime = eduTrainTimeBean.getEndTime();
        }

        if (userId != null) {
            EduTrainningRecordUser eduTrainningRecordUserR = this.getTrainRecordByUser(userId,beginTime,endTime);
            eduTrainningRecordUserList.add(eduTrainningRecordUserR);
            eduTrainningRecordUserPage.setRecords(eduTrainningRecordUserList);
            eduTrainningRecordUserPage.setTotal(eduTrainningRecordUserList.size());
        } else if (departId != null) {
            //获取到当前部门所有培训人员列表
            List<EduTrainningRecordUser> eduTrainningRecordUsers = eduTrainningRecordUserMapper.selectRecordsByDepartId(departId);
            for (EduTrainningRecordUser eduTrainningRecordUser : eduTrainningRecordUsers) {
                EduTrainningRecordUser eduTrainningRecordUserR = this.getTrainRecordByUser(eduTrainningRecordUser.getUserId(), beginTime, endTime);
                eduTrainningRecordUserList.add(eduTrainningRecordUserR);
            }
            eduTrainningRecordUserPage.setRecords(eduTrainningRecordUserList);
            eduTrainningRecordUserPage.setTotal(eduTrainningRecordUserList.size());
        } else if (jobId != null) {
            //获取当前岗位员工的所有培训员工信息列表
            List<EduTrainningRecordUser> eduTrainningRecordUsers = eduTrainningRecordUserMapper.selectRecordsByJobId(jobId);
            //遍历所有培训人员
            for (EduTrainningRecordUser eduTrainningRecordUser : eduTrainningRecordUsers) {
                EduTrainningRecordUser eduTrainningRecordUserR = this.getTrainRecordByUser(eduTrainningRecordUser.getUserId(), beginTime, endTime);
                eduTrainningRecordUserList.add(eduTrainningRecordUserR);
            }
            eduTrainningRecordUserPage.setRecords(eduTrainningRecordUserList);
            eduTrainningRecordUserPage.setTotal(eduTrainningRecordUserList.size());
        } else {
            List<EduTrainningRecordUser> eduTrainningRecordUsers = eduTrainningRecordUserMapper.selectAll();
            if (eduTrainningRecordUsers.size() == 0) {
                throw new IllegalArgumentException("无记录");
            }
            for (EduTrainningRecordUser eduTrainningRecordUser : eduTrainningRecordUsers) {
                EduTrainningRecordUser eduTrainningRecordUserR = this.getTrainRecordByUser(eduTrainningRecordUser.getUserId(), beginTime, endTime);
                eduTrainningRecordUserList.add(eduTrainningRecordUserR);
            }
            eduTrainningRecordUserPage.setRecords(eduTrainningRecordUserList);
            eduTrainningRecordUserPage.setTotal(eduTrainningRecordUserList.size());
        }
        return eduTrainningRecordUserPage;
    }

    /**
     *
     * @return
     */
    private EduTrainningRecordUser getTrainRecordByUser(Long userId,Date beginTime, Date endTime){
        //获取到了一个user的多条培训记录
        List<EduTrainningRecordUser> eduTrainningRecordUsers = eduTrainningRecordUserMapper.selectRecordsByUserId(userId, beginTime, endTime);
        double trainTimeSumUser = 0;
        //填充这个user的基本信息
        if (eduTrainningRecordUsers.size() == 0) {
            throw new IllegalArgumentException("无记录");
        }
        EduTrainningRecordUser eduTrainningRecordUserR = eduTrainningRecordUsers.get(0);
        //累加多条记录的培训学时
        for (EduTrainningRecordUser eduTrainningRecordUser : eduTrainningRecordUsers) {
            Double trainTimeSum = eduTrainningRecordUser.getTrainTimeSum();
            trainTimeSumUser += trainTimeSum;
        }
        eduTrainningRecordUserR.setTrainTimeSum(trainTimeSumUser);
        eduTrainningRecordUserR.setBeginTime(beginTime);
        eduTrainningRecordUserR.setEndTime(endTime);
        return eduTrainningRecordUserR;
    }

    /**
     *
     * @param departId
     * @return
     */
    @Override
    public IPage<EduTrainningRecord> getRecordsByDepartId (Long departId){
//        EduTrainningRecord eduTrainningRecord = eduTrainningRecordMapper.selectRecordsByDepartId(departId);
        List<EduTrainningRecord> eduTrainningRecord = eduTrainningRecordMapper.selectList(new LambdaQueryWrapper<EduTrainningRecord>()
                .eq(EduTrainningRecord::getResponsibleDept, departId)
                .eq(EduTrainningRecord::getDeleteFlag, "0"));
        if (eduTrainningRecord == null) {
            throw new IllegalArgumentException("无记录");
        }
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<EduTrainningRecord> eduTrainningRecordPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>();
        eduTrainningRecordPage.setRecords(eduTrainningRecord);
        eduTrainningRecordPage.setTotal(eduTrainningRecord.size());
        return eduTrainningRecordPage;
    }

    /**
     * 批量更新取得证书的培训记录信息
     *
     * @param records
     * @param recordIdToCertMap
     */
    private void updateRecordCertInfo(List<EduTrainningRecordUser> records,
                                      Map<Long, EduCertificateUser> recordIdToCertMap) {
        List<EduTrainningRecordUser> updateList = new ArrayList<EduTrainningRecordUser>(records.size());
        records.forEach(record -> {
            EduCertificateUser cert = recordIdToCertMap.get(record.getId());
            if (cert != null) {
                cert.setCertStatus(CertStatus.NO_EFFECTIVE.status+"");
                record.setCertUserId(cert.getId());
                updateList.add(record);
            }
        });
        eduTrainningRecordUserDao.saveAll(updateList);
    }

    private Date calculateOutofDateTime(Date takenDate, EduCertificate certificate) {
        if (CertificateTypes.LIMITED_MONTHS.is(certificate.getEffectiveType())) {
            // 定期有效，计算到期时间
            Calendar c = Calendar.getInstance();
            c.setTime(takenDate);
            c.add(Calendar.MONTH, certificate.getEffectiveDurationMonth());
            return c.getTime();
        }
        return null;
    }

}
